#include <stdio.h>
#include "Camera.h"
#include "include.h"
#include "GL/glut.h"

Camera::Camera()
{
	background = NULL;
	focusedOnGround = false;
	transitionCount = 0;
	position = Vector2D(50,50);
	velocity = Vector2D(0,0);
	acceleration = Vector2D(0,0);

	rotation = 0.0;
	rotationalVelocity = 0.0;
	rotationalAcceleration = 0.0;
	parallaxScroll = 0.0;
	size = Vector2D(50,50);
	zoomTime = 5.0;
	translationRatio = 50.0;
	translationTime =  1.0;
	transitionTime = 1.0;
	currentTransition = 0;
	currentOffset = Vector2D(0,0);
	deltaOffset= Vector2D(0,0);
	startingOffset = Vector2D(0,0);
}
Camera::Camera(Object * focusObject, TextureManager * textureManager)
{
	background = NULL;
	focusedOnGround = false;
	transitionCount = 0;
	this->textureManager = textureManager;
	this->focusObject = focusObject;
	velocity = Vector2D(0,0);
	acceleration = Vector2D(0,0);
	position = Vector2D(50,50);
	rotation = 0.0;
	rotationalVelocity = 0.0;
	rotationalAcceleration = 0.0;
	position = focusObject->position;
	position.y += 30.0;
	parallaxScroll = 0.0;
	size = Vector2D(50,50);
	zoomTime = 5.0;
	translationRatio = 50.0;
	translationTime =  1.0;
	transitionTime = 1.0;
	currentTransition = 0;
	currentOffset = Vector2D(0,0);
	deltaOffset= Vector2D(0,0);
	startingOffset = Vector2D(0,0);
}
Camera::~Camera()
{
	if(background)
		delete(background);
	background = NULL;
}
void Camera::SetSize(Vector2D newSize)
{
	size = newSize;
}
void Camera::ResetSize()
{
	size = Vector2D(50,50);
}
void Camera::ZoomIn()
{

	Vector2D minSize = MIN_CAMERA_SIZE;
	Vector2D newSize = size * 0.95;
	if(newSize.x < minSize.x)
		newSize.x = minSize.x;
	if(newSize.y < minSize.y)
		newSize.y = minSize.y;
	size = newSize;
}
void Camera::ZoomOut()
{
	Vector2D maxSize = MAX_CAMERA_SIZE;
	Vector2D newSize = size * 1.05;
	if(newSize.x > maxSize.x)
		newSize.x = maxSize.x;
	if(newSize.y > maxSize.y)
		newSize.y = maxSize.y;
	size = newSize;
}
void Camera::Draw()
{
	//printf("camera draw\n");
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0,1,0,1, -1, 1);

	glColor3f(1,1,1);
	glMatrixMode(GL_MODELVIEW);

	if(background)
		background->Draw();

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(position.x - size.x,position.x + size.x, position.y - size.y, position.y + size.y, -1, 1);
	glMatrixMode(GL_MODELVIEW);
	//printf("end camera draw\n");
}

void Camera::Think(double elapsedTime)
{
	//we want to keep the focusObject near the center of the screen.
	if(focusObject == NULL && !focusedOnGroup)
		return;


	if(!focusedOnGroup)
	{
		float velMag = focusObject->velocity.Magnitude();
		#define MAX_SPEED 1000.0
		if(velMag > MAX_SPEED)
			velMag = MAX_SPEED;
		Vector2D minSize = MIN_CAMERA_SIZE;
		Vector2D maxSize = MAX_CAMERA_SIZE;
		float diff = maxSize.Magnitude() - minSize.Magnitude();

		desiredSize = minSize + !minSize * diff * velMag/MAX_SPEED;
	}
	Vector2D sizeDiff = desiredSize - size;
	float smallPercent = size.Magnitude() * elapsedTime/zoomTime;
	if(sizeDiff.Magnitude() > smallPercent)
		sizeDiff = !sizeDiff * smallPercent;
	size = size + sizeDiff;

	Vector2D gap = Vector2D(0,0);
	if(!focusedOnGroup)
	{
		if(focusedOnGround)
		{
			if(focusObject->isOnGround)
			{
				currentTransition += elapsedTime;

			}
			else
			{
				focusedOnGround = false;
				currentTransition = 0.0;
				deltaOffset  = Vector2D(0,-20) - currentOffset;
				startingOffset = currentOffset;
			}
		}
		else
		{
			if(focusObject->isOnGround)
			{
				focusedOnGround = true;
				currentTransition = 0.0;
				deltaOffset = Vector2D(0,30) - currentOffset;
				startingOffset = currentOffset;
			}
			else
			{
				currentTransition += elapsedTime;
			}
		}

		float ratio = currentTransition / transitionTime;
		if(ratio > 1.0)
			ratio = 1.0;
		currentOffset = startingOffset + deltaOffset * ratio;//Vector2D(0.0,30.0 - transitionCount * 0.5);

		gap = (focusObject->position + currentOffset) -position;
		if(isReturning)
		{
			if(gap.Magnitude() < 5.0 && sizeDiff.Magnitude() <= smallPercent)
			{
				SetFocusObject(focusObject, false);
			}
		}
	}
	else
	{
		gap = focusPoint - position;
	}

	if(gap.Magnitude() > 0)
	{
		float tRatio = elapsedTime * translationRatio;
		if(tRatio > 1)
			tRatio = 1;
		deltaPosition =  gap * tRatio;
		position = position + deltaPosition;
		if(background)
			background->Think(deltaPosition);
	}

}
Vector2D Camera::GetPosition()
{
	return position;
}
void Camera::SetPosition(Vector2D position)
{
	this->position = position;
}
void Camera::SetBackground(Background * bg)
{
	if(this->background)
		delete(background);

	this->background = bg;
}
void Camera::SetFocusObject(Object * object, bool snap)
{

	zoomTime = 5.0;
	translationRatio = 50.0;

	focusObject = object;
	if(snap)
	{
		position = focusObject->position;
	}
	focusedOnGroup = false;
	isReturning = false;
}
void Camera::ReturnToFocusObject()
{
	ReturnToFocusObject(focusObject);
}
void Camera::ReturnToFocusObject(Object * object)
{
	focusObject = object;
	focusedOnGroup = false;
	isReturning = true;

}
void Camera::SetFocusObjectList(ObjectList * list, bool snap)
{
	focusedOnGroup = true;
	isReturning = false;

	float width = list->GetWidth();
	focusPoint = list->GetMidpoint() + Vector2D(0,width * 0.5);
	width *=2.0;
	desiredSize = Vector2D(width, width);
	zoomTime = 0.5;
	translationRatio = 5.0;
	if(snap)
	{
		position = focusPoint;
		size = desiredSize;
	}
}
Vector2D Camera::ConvertToCameraSpace(Vector2D worldPoint)
{
	Vector2D topLeft = position;
	topLeft.x -= size.x;
	topLeft.y += size.y;

	Vector2D cameraPoint = (worldPoint - topLeft);

	cameraPoint.x = cameraPoint.x * (50.0/size.x);
	cameraPoint.y = cameraPoint.y * (50.0/size.y);
	cameraPoint.y = -1.0 * cameraPoint.y;
	return cameraPoint;
}
Vector2D Camera::ConvertToWorldSpace(Vector2D cameraPoint)
{
	return Vector2D(0,0);
}
